home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xmcd-1.4 / libdi.d / os_sun.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-10  |  7.5 KB  |  349 lines

  1. /*
  2.  *   libdi - CD Audio Player Device Interface Library
  3.  *
  4.  *   Copyright (C) 1995  Ti Kan
  5.  *   E-mail: ti@amb.org
  6.  *
  7.  *   This program is free software; you can redistribute it and/or modify
  8.  *   it under the terms of the GNU General Public License as published by
  9.  *   the Free Software Foundation; either version 2 of the License, or
  10.  *   (at your option) any later version.
  11.  *
  12.  *   This program is distributed in the hope that it will be useful,
  13.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *   GNU General Public License for more details.
  16.  *
  17.  *   You should have received a copy of the GNU General Public License
  18.  *   along with this program; if not, write to the Free Software
  19.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *   This software module contains code that interfaces the CD player
  22.  *   application to the SunOS operating systems.  The name "Sun" and
  23.  *   "SunOS" are used here for identification purposes only.  This
  24.  *   software and its author are not affiliated with Sun Microsystems.
  25.  *
  26.  *   You may want to compile with -DSOL2_RSENSE on Solaris 2.2 or
  27.  *   later systems to enable the auto-request sense feature.
  28.  */
  29. #ifndef LINT
  30. static char *_os_sun_c_ident_ = "@(#)os_sun.c    5.6 94/12/28";
  31. #endif
  32.  
  33. #include "common.d/appenv.h"
  34. #include "common.d/util.h"
  35. #include "libdi.d/libdi.h"
  36. #include "libdi.d/scsipt.h"
  37.  
  38. #if defined(sun) && defined(DI_SCSIPT) && !defined(DEMO_ONLY)
  39.  
  40. extern appdata_t    app_data;
  41. extern bool_t        scsipt_notrom_error;
  42. extern FILE        *errfp;
  43.  
  44. STATIC int        pthru_fd = -1;    /* Passthrough device file desc */
  45. STATIC req_sense_data_t    sense_data;    /* Request sense data buffer */
  46.  
  47.  
  48. /*
  49.  * pthru_send
  50.  *    Build SCSI CDB and send command to the device.
  51.  *
  52.  * Args:
  53.  *    opcode - SCSI command opcode
  54.  *    addr - The "address" portion of the SCSI CDB
  55.  *    buf - Pointer to data buffer
  56.  *    size - Number of bytes to transfer
  57.  *    rsvd - The "reserved" portion of the SCSI CDB
  58.  *    length - The "length" portion of the SCSI CDB
  59.  *    param - The "param" portion of the SCSI CDB
  60.  *    control - The "control" portion of the SCSI CDB
  61.  *    rw - Data transfer direction flag (READ_OP or WRITE_OP)
  62.  *    prnerr - Whether an error message should be displayed
  63.  *         when a command fails
  64.  *
  65.  * Return:
  66.  *    TRUE - command completed successfully
  67.  *    FALSE - command failed
  68.  */
  69. bool_t
  70. pthru_send(
  71.     byte_t        opcode,
  72.     word32_t    addr,
  73.     byte_t        *buf,
  74.     word32_t    size,
  75.     byte_t        rsvd,
  76.     word32_t    length,
  77.     byte_t        param,
  78.     byte_t        control,
  79.     byte_t        rw,
  80.     bool_t        prnerr
  81. )
  82. {
  83.     struct uscsi_cmd    ucmd;
  84.     byte_t            cdb[12];
  85.  
  86.     
  87.     if (pthru_fd < 0 || scsipt_notrom_error)
  88.         return FALSE;
  89.  
  90.     memset(&ucmd, 0, sizeof(ucmd));
  91.     memset(cdb, 0, sizeof(cdb));
  92.  
  93.     /* set up SCSI CDB */
  94.     switch (opcode & 0xf0) {
  95.     case 0xa0:
  96.     case 0xe0:
  97.         /* 12-byte commands */
  98.         cdb[0] = opcode;
  99.         cdb[1] = param;
  100.         cdb[2] = (addr >> 24) & 0xff;
  101.         cdb[3] = (addr >> 16) & 0xff;
  102.         cdb[4] = (addr >> 8) & 0xff;
  103.         cdb[5] = (addr & 0xff);
  104.         cdb[6] = (length >> 24) & 0xff;
  105.         cdb[7] = (length >> 16) & 0xff;
  106.         cdb[8] = (length >> 8) & 0xff;
  107.         cdb[9] = length & 0xff;
  108.         cdb[10] = rsvd;
  109.         cdb[11] = control;
  110.  
  111.         ucmd.uscsi_cdblen = 12;
  112.         break;
  113.  
  114.     case 0xc0:
  115.     case 0xd0:
  116.     case 0x20:
  117.     case 0x30:
  118.     case 0x40:
  119.         /* 10-byte commands */
  120.         cdb[0] = opcode;
  121.         cdb[1] = param;
  122.         cdb[2] = (addr >> 24) & 0xff;
  123.         cdb[3] = (addr >> 16) & 0xff;
  124.         cdb[4] = (addr >> 8) & 0xff;
  125.         cdb[5] = addr & 0xff;
  126.         cdb[6] = rsvd;
  127.         cdb[7] = (length >> 8) & 0xff;
  128.         cdb[8] = length & 0xff;
  129.         cdb[9] = control;
  130.  
  131.         ucmd.uscsi_cdblen = 10;
  132.         break;
  133.  
  134.     case 0x00:
  135.     case 0x10:
  136.         /* 6-byte commands */
  137.         cdb[0] = opcode;
  138.         cdb[1] = param;
  139.         cdb[2] = (addr >> 8) & 0xff;
  140.         cdb[3] = addr & 0xff;
  141.         cdb[4] = length & 0xff;
  142.         cdb[5] = control;
  143.  
  144.         ucmd.uscsi_cdblen = 6;
  145.         break;
  146.  
  147.     default:
  148.         if (app_data.scsierr_msg && prnerr)
  149.             fprintf(errfp, "0x%02x: Unknown SCSI opcode\n",
  150.                 opcode);
  151.         return FALSE;
  152.     }
  153.  
  154.     DBGDUMP("SCSI CDB bytes", cdb, ucmd.uscsi_cdblen);
  155.         
  156.     /* set up uscsi_cmd */
  157.     ucmd.uscsi_cdb = (caddr_t) cdb;
  158.     ucmd.uscsi_bufaddr = (caddr_t) buf;
  159.     ucmd.uscsi_buflen = (int) size;
  160.     ucmd.uscsi_flags = USCSI_SILENT | USCSI_ISOLATE;
  161.     if (size != 0)
  162.         ucmd.uscsi_flags |= (rw == READ_OP) ? USCSI_READ : USCSI_WRITE;
  163.  
  164. #if defined(SVR4) && defined(SOL2_RSENSE)
  165.     ucmd.uscsi_flags |= USCSI_RQENABLE;
  166.     ucmd.uscsi_rqbuf = (caddr_t) &sense_data;
  167.     ucmd.uscsi_rqlen = SZ_RSENSE;
  168. #endif
  169.  
  170.     /* Send the command down via the "pass-through" interface */
  171.     if (ioctl(pthru_fd, USCSICMD, &ucmd) < 0) {
  172.         if (app_data.scsierr_msg && prnerr)
  173.             perror("USCSICMD ioctl failed");
  174.         return FALSE;
  175.     }
  176.  
  177.     if (ucmd.uscsi_status != USCSI_STATUS_GOOD) {
  178.         if (app_data.scsierr_msg && prnerr) {
  179.             fprintf(errfp, "CD audio: %s %s:\n%s=0x%x %s=0x%x\n",
  180.                 "SCSI command fault on",
  181.                 app_data.device,
  182.                 "Opcode",
  183.                 opcode,
  184.                 "Status",
  185.                 ucmd.uscsi_status);
  186.         }
  187.  
  188. #if defined(SVR4) && defined(SOL2_RSENSE)
  189.         if (ucmd.uscsi_rqstatus == USCSI_STATUS_GOOD &&
  190.             app_data.scsierr_msg && prnerr) {
  191.             fprintf(errfp, " Key=0x%x Code=0x%x Qual=0x%x\n",
  192.                 sense_data.key,
  193.                 sense_data.code,
  194.                 sense_data.qual);
  195.         }
  196. #else    /* SVR4 SOL2_RSENSE */
  197.         /* Send Request Sense command */
  198.         cdb[0] = OP_S_RSENSE;
  199.         cdb[1] = 0;
  200.         cdb[2] = 0;
  201.         cdb[3] = 0;
  202.         cdb[4] = (byte_t) SZ_RSENSE;
  203.         cdb[5] = 0;
  204.  
  205.         ucmd.uscsi_cdblen = 6;
  206.         ucmd.uscsi_cdb = (caddr_t) cdb;
  207.         ucmd.uscsi_bufaddr = (caddr_t) &sense_data;
  208.         ucmd.uscsi_buflen = (int) SZ_RSENSE;
  209.         ucmd.uscsi_flags = USCSI_READ;
  210.  
  211.         if (ioctl(pthru_fd, USCSICMD, &ucmd) < 0 ||
  212.             sense_data.valid == 0) {
  213.             if (app_data.scsierr_msg && prnerr)
  214.                 fprintf(errfp, "\n");
  215.         }
  216.         else if (app_data.scsierr_msg && prnerr) {
  217.             fprintf(errfp, " Key=0x%x Code=0x%x Qual=0x%x\n",
  218.                 sense_data.key,
  219.                 sense_data.code,
  220.                 sense_data.qual);
  221.         }
  222. #endif    /* SVR4 SOL2_RSENSE */
  223.  
  224.         return FALSE;
  225.     }
  226.  
  227.     return TRUE;
  228. }
  229.  
  230.  
  231. /*
  232.  * pthru_open
  233.  *    Open SCSI pass-through device
  234.  *
  235.  * Args:
  236.  *    path - device path name string
  237.  *
  238.  * Return:
  239.  *    TRUE - open successful
  240.  *    FALSE - open failed
  241.  */
  242. bool_t
  243. pthru_open(char *path)
  244. {
  245.     struct stat    stbuf;
  246.     char        errstr[ERR_BUF_SZ];
  247.  
  248.     /* Check for validity of device node */
  249.     if (stat(path, &stbuf) < 0) {
  250.         if (errno != ENOENT) {
  251.             sprintf(errstr, app_data.str_staterr, path);
  252.             cd_fatal_popup(app_data.str_fatal, errstr);
  253.         }
  254.         return FALSE;
  255.     }
  256.     if (!S_ISCHR(stbuf.st_mode)) {
  257.         sprintf(errstr, app_data.str_noderr, path);
  258.         cd_fatal_popup(app_data.str_fatal, errstr);
  259.         return FALSE;
  260.     }
  261.  
  262.     if ((pthru_fd = open(path, O_RDONLY)) < 0) {
  263.         DBGPRN(errfp, "Cannot open %s: errno=%d\n", path, errno);
  264.         return FALSE;
  265.     }
  266.  
  267.     return TRUE;
  268. }
  269.  
  270.  
  271. /*
  272.  * pthru_close
  273.  *    Close SCSI pass-through device
  274.  *
  275.  * Args:
  276.  *    Nothing.
  277.  *
  278.  * Return:
  279.  *    Nothing.
  280.  */
  281. void
  282. pthru_close(void)
  283. {
  284.     if (pthru_fd >= 0) {
  285.         close(pthru_fd);
  286.         pthru_fd = -1;
  287.     }
  288. }
  289.  
  290.  
  291. /*
  292.  * pthru_vers
  293.  *    Return OS Interface Module version string
  294.  *
  295.  * Args:
  296.  *    Nothing.
  297.  *
  298.  * Return:
  299.  *    Module version text string.
  300.  */
  301. char *
  302. pthru_vers(void)
  303. {
  304. #ifdef SVR4
  305.     return ("OS Interface module (for SunOS 5.x)\n");
  306. #else
  307.     return ("OS Interface module (for SunOS 4.x)\n");
  308. #endif
  309. }
  310.  
  311.  
  312. #if defined(SVR4)
  313.  
  314. /*
  315.  * sol2_volmgt_eject
  316.  *    Use a special Solaris 2 ioctl to eject the CD.  This is required if
  317.  *    the system is running the Sun Volume Manager.  Note that the use
  318.  *    of this ioctl is likely to be incompatible with SCSI-1 CD-ROM
  319.  *    drives.
  320.  *
  321.  * Args:
  322.  *    Nothing.
  323.  *
  324.  * Return:
  325.  *    TRUE - eject successful
  326.  *    FALSE - eject failed
  327.  */
  328. bool_t
  329. sol2_volmgt_eject(void)
  330. {
  331.     int    ret;
  332.  
  333.     DBGPRN(errfp, "Sending DKIOCEJECT ioctl\n");
  334.  
  335.     if ((ret = ioctl(pthru_fd, DKIOCEJECT, 0)) < 0) {
  336.         if (app_data.scsierr_msg)
  337.             perror("DKIOCEJECT failed");
  338.         return FALSE;
  339.     }
  340.  
  341.     return TRUE;
  342. }
  343.  
  344. #endif    /* SVR4 */
  345.  
  346.  
  347. #endif    /* sun DI_SCSIPT DEMO_ONLY */
  348.  
  349.